package it.allerj.analysis;

import blobDetection.EdgeVertex;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.color.ColorSpace;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class TestAnalysis {

    public static void test(BufferedImage image) throws Exception {
        
        // instance a FilmAnalyzer and INIT! pass a dummy filter, it's enough...
        FilmAnalyzer analyzer = new FilmAnalyzer(image, 9, 9);
        
        // configure analyzer
        analyzer.refPointThreshold = 0.3f;
        analyzer.foodPointThresholdStart = 0.8f;
        analyzer.foodPointThresholdEnd = 0.96f;
        analyzer.foodPointSamplingSteps = 15;
        analyzer.circularityTolerance = 0.3f;
        
        // init analysis system
        if (!analyzer.init( new BlobDummyFilter() )) {
            System.out.println("Unable to find black reference points!");
            return;
        }

        // retrieve reference marks to paint them
        //ArrayList<DotMark> refs = analyzer.getRefDotMarks();         
        //paintRefWithCircles(image, refs);

        // configure a suitable filter to discard bad blobs
        // instance a Blob filtering object to discard bad blobs
        BlobFoodFilter filter = new BlobFoodFilter();
        
        // set blob filter global configuration
        filter.whRatioTolerance = 0.3f;
        filter.minAreaTolerancePerc = 30;
        filter.maxAreaTolerancePerc = 90;
        
        // for every cell, retrieve mark if one was found        
        ArrayList<DotMark> markersList = new ArrayList<DotMark>();
        for (int i = 1; i < 2; i++) {
            for (int j = 0; j < 9; j++) {
                System.out.println("\ncella ("+i+","+j+")");
                
                // retrieve image area where to find dot mark
                BufferedImage cellImage = analyzer.getSamplingCell(i, j).image;
                
                // refine filter configuration
                filter.imageWidth = cellImage.getWidth();
                filter.imageHeight = cellImage.getHeight();
                
                // retrieve dotmark and store it (could be an empty DotMark)
                markersList.add(analyzer.getFoodDotMark(cellImage, filter));
            }
        }
        
        paintMarkers(image, markersList, false);
        paintMarkers(image, markersList, true);
        //paintSquareOfDotMark(image, pointBPSList);
        
        showImageJFrame(image);
    }

    public static void main(String[] args) throws IOException {
        try {

            File file = new File("c:\\fava3.jpg");
            //File file = new File("/Users/masci/fava/favona.jpg");

            BufferedImage img = ImageIO.read(file);

            test(img);

        } catch (Exception ex) {
            Logger.getLogger(TestAnalysis.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static BufferedImage convertToGrayscale(BufferedImage source) {
        BufferedImageOp op = new ColorConvertOp(
                ColorSpace.getInstance(ColorSpace.CS_GRAY), null);

        return op.filter(source, null);
    }

    private static void paintRefWithCircles(BufferedImage image, ArrayList<DotMark> refs) {
        Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.red);
        for (DotMark d : refs) {
            g2d.fill(new Ellipse2D.Float( 
                    d.getUpperLeftCorner().x,
                    d.getUpperLeftCorner().y,
                    d.getDiameter(), d.getDiameter()));
        }
        g2d.dispose();
    }

    private static void paintMarkers(BufferedImage image, 
            ArrayList<DotMark> pointList, boolean byEdges) {
        Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.green);
        for (DotMark d : pointList) {
            if (byEdges) {                
                g2d.setColor(Color.green);
                ArrayList<EdgeVertex> v = d.getVertexes();
                for (int i=0; i<v.size()-1; ++i) {
                    Point.Float p1 = new Point.Float(v.get(i).x, v.get(i).y);
                    Point.Float p2 = new Point.Float(v.get(i+1).x, v.get(i+1).y);
                    p1 = d.mapToWorld(d.deNormalize(p1));
                    p2 = d.mapToWorld(d.deNormalize(p2));

                    g2d.draw( new Line2D.Float(p1, p2) );
                }
                
            } else {
                g2d.setColor(Color.RED);
                Point.Float ulc = d.getUpperLeftCorner();
                ulc = d.mapToWorld(ulc);
                g2d.draw( new Rectangle2D.Float( ulc.x, ulc.y,
                        d.getDiameter(), d.getDiameter()) );
            }  
        }

        g2d.dispose();
    }

    private static void paintSquareOfDotMark(BufferedImage image, List<DotMark> pointBPSList) {
        /*Graphics2D g2d = image.createGraphics();
        g2d.setColor(Color.blue);
        for (BlobPainterSupport pointBPS : pointBPSList) {
            DotMark maxDotMark = pointBPS.getDotMark();
            double widthA = maxDotMark.cropTop.x;
            double heightA = maxDotMark.cropTop.y;
            double widthB = maxDotMark.cropBottom.x;
            double heightB = maxDotMark.cropBottom.y;
            g2d.draw(new Line2D.Double(widthA, heightA, widthB, heightA));
            g2d.draw(new Line2D.Double(widthB, heightA, widthB, heightB));
            g2d.draw(new Line2D.Double(widthB, heightB, widthA, heightB));
            g2d.draw(new Line2D.Double(widthA, heightB, widthA, heightA));
        }
        g2d.dispose();*/
    }
    
    public static void showImageJFrame(BufferedImage image) {
        Icon icon = new ImageIcon(image);
        JLabel label = new JLabel(icon);

        final JFrame f = new JFrame("AllerJ");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(label);
        f.pack();
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}
